#include "SimulateSPI.h"

/**
 * 控制片选Pin (NSS CS )
 */
void SimulateSPI_WriteNSS(uint8_t BitVal)
{
    GPIO_WriteBit(SimulateSPI_PORT, SimulateSPI_NSS_PIN, (BitAction)BitVal);
}

/**
 * 采用SPI模式3(CPOL=1(SCK串行时钟线空闲是为高电平1),CPHA=1);
 */
void SimulateSPI_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    //
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    // M主机输入
    GPIO_InitStructure.GPIO_Pin = SimulateSPI_MISO_PIN; // PB14
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;       // 输入
    GPIO_Init(SimulateSPI_PORT, &GPIO_InitStructure);
    // M主机输出(数据线和时钟线)
    GPIO_InitStructure.GPIO_Pin = SimulateSPI_MOSI_PIN | SimulateSPI_SCK_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // PB13|15 推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SimulateSPI_PORT, &GPIO_InitStructure);
    // S从机-CS(选择)
    GPIO_InitStructure.GPIO_Pin = SimulateSPI_NSS_PIN; // (STM32硬件NSS只有一个)
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(SimulateSPI_PORT, &GPIO_InitStructure);

    GPIO_WriteBit(SimulateSPI_PORT, SimulateSPI_SCK_PIN, (BitAction)1); // SCK空闲(1)
    SimulateSPI_WriteNSS(1);                                            // 默认不选从机
}

/**
 * 选中S从机
 */
void SimulateSPI_Start(void)
{
    SimulateSPI_WriteNSS(0); // 选中S从机
}

/**
 * SPI交换一个字节
 * 采用SPI模式3(CPOL=1(SCK串行时钟线空闲是为高电平1),CPHA=1);
 * (1->0->1),数据在SCK时钟的前边沿(1->0)切换电平状态,在SCK时钟的后边沿(0->1)被采样;。
 */
uint8_t SimulateSPI_SwapByte(uint8_t b)
{
    uint8_t i = 0;
    uint8_t result = 0x00;
    for (i = 0; i < 8; i++)
    {
        GPIO_WriteBit(SimulateSPI_PORT, SimulateSPI_SCK_PIN, (BitAction)0);                                  // SCK时钟(1->0),切换电平状态
        GPIO_WriteBit(SimulateSPI_PORT, SimulateSPI_MOSI_PIN, (BitAction)((b & (0x80 >> i)) / (0x80 >> i))); // M主机发送的数据(从高位开始)
        GPIO_WriteBit(SimulateSPI_PORT, SimulateSPI_SCK_PIN, (BitAction)1);                                  // SCK时钟(1->0),采样电平
        if (GPIO_ReadInputDataBit(SimulateSPI_PORT, SimulateSPI_MISO_PIN) == 1)
        {
            result = (result | (0x80 >> i)); // M主机接收(从高位开始)
        }
    }
    return result;
}

/**
 * 释放S从机
 */
void SimulateSPI_Stop(void)
{
    SimulateSPI_WriteNSS(1); // 释放S从机
}
